//
// Created by chenxp on 2025/8/27.
//

#ifndef APPCONFIG_H
#define APPCONFIG_H
#include <string>
#include <unordered_map>
#include <mutex>

class AppConfig {
private:
    // 私有对象，单例模式。 static修饰，是为了getInstance()能够访问。
    // 这是一个裸指针,需要手动析构
    static AppConfig *instance;

    // 私有构造函数私有化，避免被创建
    AppConfig();

    // 析构函数
    // 1. 调用所有成员对象的析构函数；
    // 2. 释放类中定义的成员（比如 std::string、std::vector，它们自己会管理内存）；
    // 3. 不做额外的事（比如关闭文件、释放手动申请的资源、析构裸指针）；
    ~AppConfig();

    // std::mutex: 用于多线程同步，保护共享数据不被同时访问, 保证线程安全。提供 lock(), unlock(), try_lock()方法。
    // mutable: 可变修饰符, 允许在 const成员函数中修改该成员。
    // 这里声明的时候，就会被初始化对象（不是null）,如同int被随机赋值整数。
    mutable std::mutex mu_;

    // map<string, string>键值对
    // 这里声明的时候，就会被初始化对象（不是null）,如同int被随机赋值整数。
    std::unordered_map<std::string, std::string> kv_;

public:
    // 提供静态方法获取单例对象
    static AppConfig* getInstance();

    // 加载配置文件信息到kv_
    void loadFileConfig(const std::string &filePath);

    // 获取字符串配置项
    // 1. 第一个 const：保证 key 参数在函数体内不能被修改。
    // 2. def = ""，表示默认值是空字符串；当找不到 key 时，就返回这个默认值。
    // 3. 第二个 const：保证该函数不会修改类的成员变量（mutable修饰除外），即这是一个“只读函数”。
    // 3.1. 尾部 const 只保证类的非 mutable 成员变量不能被修改。
    // 3.2. 与类无关的变量（局部变量、全局变量、静态变量）是可以修改的。
    // 3.3. 如果成员是指针/引用，那么不能改指针本身，但能改它指向的内容。
    std::string getString(const std::string &key, const std::string& def = "") const;

    // 获取整型配置项
    // 第一个 const：保证 key 参数在函数体内不能被修改。
    int getInt(const std::string &key, int def = 0) const;

    // 判断配置项是否存在，存在返回1，不存在返回0
    // 第一个 const：保证 key 参数在函数体内不能被修改。
    bool contains(const std::string& key) const;

    // 禁止拷贝/移动
    // 拷贝构造函数的声明: 参数是const AppConfig&，= delete表示“这个函数被禁止使用”。如AppConfig a = b，会编译失败。
    AppConfig(const AppConfig&) = delete;
    // 拷贝赋值运算符声明：参数是const AppConfig&，= delete表示“这个函数被禁止使用”。如 a = b，会编译失败。
    AppConfig &operator=(const AppConfig&) = delete;
    // 移动构造函数的声明: 参数是AppConfig&&，= delete表示“这个函数被禁止使用”。如AppConfig a = std::move(b)，会编译失败。
    AppConfig(AppConfig &&) = delete;
    // 移动赋值运算符声明：参数是AppConfig&&，= delete表示“这个函数被禁止使用”。如 a = std::move(b)，会编译失败。
    AppConfig &operator=(AppConfig &&) = delete;
};

#endif //APPCONFIG_H
